/*
*  Copyright 2019-2020 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package me.zhengjie.modules.app.income.service.impl;

import com.alibaba.fastjson.JSON;
import freemarker.template.utility.StringUtil;
import me.zhengjie.modules.app.ad.repository.AduserXHotelRepository;
import me.zhengjie.modules.app.ad.service.AduserXHotelService;
import me.zhengjie.modules.app.ad.service.dto.AduserXHotelDto;
import me.zhengjie.modules.app.ad.service.dto.AduserXHotelQueryCriteria;
import me.zhengjie.modules.app.hotel.service.dto.HotelInfoDto;
import me.zhengjie.modules.app.income.domain.IncomeInfo;
import me.zhengjie.utils.*;
import lombok.RequiredArgsConstructor;
import me.zhengjie.modules.app.income.repository.IncomeInfoRepository;
import me.zhengjie.modules.app.income.service.IncomeInfoService;
import me.zhengjie.modules.app.income.service.dto.IncomeInfoDto;
import me.zhengjie.modules.app.income.service.dto.IncomeInfoQueryCriteria;
import me.zhengjie.modules.app.income.service.mapstruct.IncomeInfoMapper;
import me.zhengjie.modules.app.params.domain.ParamsInfo;
import me.zhengjie.modules.app.params.repository.ParamsInfoRepository;
import me.zhengjie.modules.app.params.service.ParamsInfoService;
import me.zhengjie.modules.app.params.service.dto.ParamsInfoDto;
import me.zhengjie.modules.app.params.service.dto.ParamsInfoQueryCriteria;
import me.zhengjie.modules.app.record.domain.RecordDetailInfo;
import me.zhengjie.modules.app.record.domain.RecordInfo;
import me.zhengjie.modules.app.record.repository.RecordInfoRepository;
import me.zhengjie.modules.security.service.dto.JwtUserDto;
import me.zhengjie.modules.system.service.dto.DeptDto;
import me.zhengjie.modules.system.service.dto.UserDto;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.hutool.core.util.IdUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;

import javax.servlet.http.HttpServletResponse;

import static java.time.format.DateTimeFormatter.ISO_DATE;

/**
* @website https://el-admin.vip
* @description 服务实现
* @author Haojie Li
* @date 2021-03-02
**/
@Service
@RequiredArgsConstructor
public class IncomeInfoServiceImpl implements IncomeInfoService {

    private final IncomeInfoRepository incomeInfoRepository;
    private final IncomeInfoMapper incomeInfoMapper;

//    private final ParamsInfoRepository paramsInfoRepository;

    private final AduserXHotelService aduserXHotelService;
//    private final RecordInfoRepository recordInfoRepository;
    private final ParamsInfoService paramsInfoService;

    @Override
    public Map<String,Object> queryAll(IncomeInfoQueryCriteria criteria, Pageable pageable){
        Page<IncomeInfo> page = incomeInfoRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(incomeInfoMapper::toDto));
    }

    @Override
    public List<IncomeInfoDto> queryAll(IncomeInfoQueryCriteria criteria){
        return incomeInfoMapper.toDto(incomeInfoRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    @Transactional
    public IncomeInfoDto findById(String id) {
        IncomeInfo incomeInfo = incomeInfoRepository.findById(id).orElseGet(IncomeInfo::new);
        ValidationUtil.isNull(incomeInfo.getId(),"IncomeInfo","id",id);
        return incomeInfoMapper.toDto(incomeInfo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public IncomeInfoDto create(IncomeInfo resources) {
        resources.setId(IdUtil.simpleUUID());
        resources.setCreateBy(SecurityUtils.getCurrentUsername());
        resources.setCreateTime(LocalDateTime.now());
        resources.setIsEnable(1);
        return incomeInfoMapper.toDto(incomeInfoRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(IncomeInfo resources) {
    	resources.setUpdateBy(SecurityUtils.getCurrentUsername());
    	resources.setUpdateTime(LocalDateTime.now());

        IncomeInfo incomeInfo = incomeInfoRepository.findById(resources.getId()).orElseGet(IncomeInfo::new);
        ValidationUtil.isNull( incomeInfo.getId(),"IncomeInfo","id",resources.getId());
        incomeInfo.copy(resources);
        incomeInfoRepository.save(incomeInfo);
    }

    @Override
    public void deleteAll(String[] ids) {
        for (String id : ids) {
            incomeInfoRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<IncomeInfoDto> all, HttpServletResponse response) throws IOException {
    	DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        List<Map<String, Object>> list = new ArrayList<>();
        for (IncomeInfoDto incomeInfo : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("酒店ID", incomeInfo.getHotelId());
            map.put("酒店名称", incomeInfo.getHotelName());
            map.put("酒店房间ID", incomeInfo.getHotelRoomId());
            map.put("酒店房间号", incomeInfo.getHotelRoomNo());
            map.put("设备IP", incomeInfo.getIp());
            map.put("设备MAC", incomeInfo.getMac());
            map.put("单价", incomeInfo.getPrice());
            map.put("有效时长", incomeInfo.getLimitTime());
            map.put("总的开机时间差", incomeInfo.getTimeReslut());
            map.put("收益额", incomeInfo.getIncomeMoney());
            map.put("收益月份", incomeInfo.getMonth());
            map.put("是否结算：1、表示未结算  2、表示结算中  0、表示已结算", incomeInfo.getIsClose());
            map.put("创建者", incomeInfo.getCreateBy());
            map.put("更新者", incomeInfo.getUpdateBy());
            map.put("创建时间", incomeInfo.getCreateTime()  == null ? "" : dtf.format(incomeInfo.getCreateTime()));
            map.put("更新时间", incomeInfo.getUpdateTime() == null ? "" : dtf.format(incomeInfo.getUpdateTime()));
            map.put("数据状态", incomeInfo.getIsEnable());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

	@Override
	public void computeIncome(RecordDetailInfo resources) {
		// TODO Auto-generated method stub
		//查询酒店对应的广告商
		AduserXHotelQueryCriteria aduserXHotelQueryCriteria = new AduserXHotelQueryCriteria();
		aduserXHotelQueryCriteria.setHotelId(resources.getHotelId());

		List<AduserXHotelDto> aduserXHotelDtos = aduserXHotelService.queryAll(aduserXHotelQueryCriteria);
		if(aduserXHotelDtos != null && aduserXHotelDtos.size() > 0){
			AduserXHotelDto aduserXHotelDto = aduserXHotelDtos.get(0);

			ParamsInfoQueryCriteria paramsInfoQueryCriteria = new ParamsInfoQueryCriteria();
			paramsInfoQueryCriteria.setAdUserId(aduserXHotelDto.getUserId());

			List<ParamsInfoDto> paramsInfoDtos = paramsInfoService.queryAll(paramsInfoQueryCriteria);
			ParamsInfoDto paramsInfoDto = paramsInfoDtos.get(0);

			//获取当前设置的单价
			double price = Double.parseDouble(paramsInfoDto.getPrice());

			int time = Integer.parseInt(paramsInfoDto.getTimeLimit()) * 60;//转成秒

			List<Map<String,Object>> lists = incomeInfoRepository.findInComeByDetailId(resources.getId());
			IncomeInfo incomeInfo = null;
			List<IncomeInfo> incomes = new ArrayList<IncomeInfo>();
			Map<String,Object> maps = null;
			BigDecimal tempPrice = new BigDecimal(Double.toString(price));
			BigDecimal times = new BigDecimal(Double.toString(0));
			if(lists != null && lists.size() > 0) {
				for(int index = 0 ; index < lists.size(); index ++) {
					times = new BigDecimal(Double.toString(0));
					maps = lists.get(index);
					incomeInfo = new IncomeInfo();
					incomeInfo.setId(IdUtil.simpleUUID());
					incomeInfo.setHotelId(maps.get("hotel_id").toString());
					incomeInfo.setHotelName(maps.get("hotel_name").toString());
					incomeInfo.setHotelRoomId(maps.get("hotel_room_id").toString());
					incomeInfo.setHotelRoomNo(maps.get("hotel_room_no").toString());
					incomeInfo.setIp(maps.get("ip") == null ? "" : maps.get("ip").toString());
					incomeInfo.setMac(maps.get("mac") == null ? "" : maps.get("mac").toString());
					incomeInfo.setTimeReslut(Integer.parseInt(maps.get("time_result").toString())  / 60);
					incomeInfo.setPrice(price + "");
					incomeInfo.setLimitTime(time / 60);
					if(incomeInfo.getTimeReslut() >= incomeInfo.getLimitTime()) {
						times = new BigDecimal(Double.toString(1));
					}
					incomeInfo.setIncomeMoney(tempPrice.multiply(times).toString());
					incomeInfo.setBelongDate(LocalDate.parse(maps.get("belong_date").toString()));

					incomeInfo.setIsClose(1);//1、表示未结算  2、表示结算中  0、表示已结算
					incomeInfo.setIsEnable(1);
					incomes.add(incomeInfo);
				}
			}
			incomeInfoRepository.saveAll(incomes);
		}



	}

	@Override
	public Map<String,Object> findIncomeBetweenDate(IncomeInfoQueryCriteria criteria, Pageable pageable) {
		// TODO Auto-generated method stub
		LocalDate startBelongDate = null;
		LocalDate endBelongDate = null;
		if(criteria.getBelongDate() != null) {
			startBelongDate = LocalDate.of(criteria.getBelongDate().getYear(),criteria.getBelongDate().getMonth(),1);
			endBelongDate = criteria.getBelongDate().with(TemporalAdjusters.lastDayOfMonth());

		}
		String hotels = new String();
//		判断是否有广告商参数
		if(criteria.getAdUserId() != null) {
			//查询用户是否属于广告商这一类用户，广告商有设置所管理的酒店AduserXHotel
			AduserXHotelQueryCriteria aduserXHotelQueryCriteria = new AduserXHotelQueryCriteria();
			aduserXHotelQueryCriteria.setUserId(criteria.getAdUserId());
			List<AduserXHotelDto> aduserXHotelDtos = aduserXHotelService.queryAll(aduserXHotelQueryCriteria);
			Set<String> hotelIds = aduserXHotelDtos.stream().map(AduserXHotelDto::getHotelId).collect(Collectors.toSet());
			Iterator it = hotelIds.iterator();
			while (it.hasNext()) {
				String next = (String) it.next();
				hotels+=(next+",");
			}
			hotels= hotels.substring(0, hotels.length() - 1);
		}

		//获取用户权限
		JwtUserDto jwtUserDto = (JwtUserDto) SecurityUtils.getCurrentUser();

		UserDto userDto = jwtUserDto.getUser();
		List<HotelInfoDto> hotelLists = new ArrayList<HotelInfoDto>(userDto.getHotels());
		if(hotelLists.size() == 1) {
			criteria.setHotelId(hotelLists.get(0).getId().toString());
			hotels=hotelLists.get(0).getId();
		}

		if(criteria.getIsClose() == null) {
			Page<Map<String,Object>> page = incomeInfoRepository.findIncomeBetweenDate(startBelongDate, endBelongDate, hotels, pageable);
	        return PageUtil.toPage(page);
		}else {
			Page<Map<String,Object>> page = incomeInfoRepository.findIncomeBetweenDate(startBelongDate, endBelongDate,criteria.getIsClose(), hotels, pageable);

			return PageUtil.toPage(page);
		}
	}

	@Override
	public Map<String,Object> findInComeByHotelId(IncomeInfoQueryCriteria criteria, Pageable pageable) {
		// TODO Auto-generated method stub
		LocalDate startBelongDate = null;
		LocalDate endBelongDate = null;
		if(criteria.getBelongDate() != null) {
			startBelongDate = LocalDate.of(criteria.getBelongDate().getYear(),criteria.getBelongDate().getMonth(),1);
			endBelongDate = criteria.getBelongDate().with(TemporalAdjusters.lastDayOfMonth());

		}


		if(criteria.getIsClose() == null) {
			Page<IncomeInfo> page = incomeInfoRepository.findInComeByHotelId(startBelongDate, endBelongDate,criteria.getHotelId(), pageable);
	        return PageUtil.toPage(page);
		}else {
			Page<IncomeInfo> page = incomeInfoRepository.findInComeByHotelId(startBelongDate, endBelongDate,criteria.getHotelId(),criteria.getIsClose(), pageable);
	        return PageUtil.toPage(page);
		}
	}

	@Override
	public List<IncomeInfo> findInComeByHotelIdDownload(IncomeInfoQueryCriteria criteria) {
		// TODO Auto-generated method stub
		// TODO Auto-generated method stub
		LocalDate startBelongDate = LocalDate.of(criteria.getBelongDate().getYear(),criteria.getBelongDate().getMonth(),1);
		LocalDate endBelongDate = criteria.getBelongDate().with(TemporalAdjusters.lastDayOfMonth());

		if(criteria.getIsClose() == null) {
			List<IncomeInfo> page = incomeInfoRepository.findInComeByHotelIdDownload(startBelongDate, endBelongDate,criteria.getHotelId());
	        return page;
		}else {
			List<IncomeInfo> page = incomeInfoRepository.findInComeByHotelIdDownload(startBelongDate, endBelongDate,criteria.getHotelId(),criteria.getIsClose());
	        return page;
		}
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void updateIsCloseByHotelId(IncomeInfo resources) {
		// TODO Auto-generated method stub
		LocalDate startBelongDate = LocalDate.of(resources.getBelongDate().getYear(),resources.getBelongDate().getMonth(),1);
		LocalDate endBelongDate = resources.getBelongDate().with(TemporalAdjusters.lastDayOfMonth());
		incomeInfoRepository.updateIsCloseByHotelId(startBelongDate, endBelongDate, resources.getHotelId(), resources.getIsClose());
	}

	@Override
	public void exportBenefitDetails(IncomeInfoQueryCriteria criteria, HttpServletResponse response)throws IOException {
		JwtUserDto jwtUserDto = (JwtUserDto) SecurityUtils.getCurrentUser();
		UserDto userDto = jwtUserDto.getUser();
		List<HotelInfoDto> hotelLists = new ArrayList<HotelInfoDto>(userDto.getHotels());
		String ids=null;
		LocalDate startTime=null;
		LocalDate endTime=null;
		if(StringUtils.hasText(criteria.getHotelId())){
			ids=criteria.getHotelId();
			startTime = LocalDate.of(criteria.getBelongDate().getYear(),criteria.getBelongDate().getMonth(),1);
			endTime = criteria.getBelongDate().with(TemporalAdjusters.lastDayOfMonth());
		}else {
			if(hotelLists.size()!=0){
			for (int i = 0; i < hotelLists.size(); i++) {
				ids=hotelLists.get(i).getId()+",";
			}
			ids=ids.substring(0,ids.length()-1);
			}
			startTime = criteria.getStartBelongDate();
			endTime = criteria.getEndBelongDate();
		}
		List<IncomeInfo> inComeByHotelIdExportList = incomeInfoRepository.findInComeByHotelIdExport(startTime,endTime,ids);
		export(inComeByHotelIdExportList,response);
	}

	private void export(List<IncomeInfo> IncomeInfos, HttpServletResponse response) throws IOException {
	List<Map<String, Object>> list = new ArrayList<>();
	for (IncomeInfo incomeInfo : IncomeInfos) {
		DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
			Map<String,Object> map = new LinkedHashMap<>();
			map.put("酒店名称", incomeInfo.getHotelName());
			map.put("酒店房间号", incomeInfo.getHotelRoomNo());
			map.put("单价", incomeInfo.getPrice());
			map.put("有效时长", incomeInfo.getLimitTime());
			map.put("开机时间", incomeInfo.getTimeReslut());
			map.put("收益额",incomeInfo.getIncomeMoney());
			map.put("受益月份",incomeInfo.getBelongDate()==null?"":dtf.format(incomeInfo.getBelongDate()));
			list.add(map);
	}
	FileUtil.downloadExcel(list, response);
	}

	@Override
	public List<Map<String, Object>> findIncomeBetweenDateAll(IncomeInfoQueryCriteria criteria) {
		// TODO Auto-generated method stub
		LocalDate startBelongDate = LocalDate.of(criteria.getBelongDate().getYear(),criteria.getBelongDate().getMonth(),1);
		LocalDate endBelongDate = criteria.getBelongDate().with(TemporalAdjusters.lastDayOfMonth());

		//获取用户权限
		JwtUserDto jwtUserDto = (JwtUserDto) SecurityUtils.getCurrentUser();

		UserDto userDto = jwtUserDto.getUser();
		List<HotelInfoDto> hotelLists = new ArrayList<HotelInfoDto>(userDto.getHotels());
		if(hotelLists.size() == 1) {
			criteria.setHotelId(hotelLists.get(0).getId().toString());
		}

		if(criteria.getIsClose() == null) {
			List<Map<String,Object>> page = incomeInfoRepository.findIncomeBetweenDateAll(startBelongDate, endBelongDate, criteria.getHotelId());
	        return page;
		}else {
			List<Map<String,Object>> page = incomeInfoRepository.findIncomeBetweenDateAll(startBelongDate, endBelongDate,criteria.getIsClose(), criteria.getHotelId());
	        return page;
		}
	}

	@Override
	public void downloadCustomer(List<Map<String, Object>> all, HttpServletResponse response) throws IOException {
		// TODO Auto-generated method stub
		DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        List<Map<String, Object>> list = new ArrayList<>();
//        {bindId=null, hotelId=0001, hotelName=重庆大酒店, hotelRoomId=aea0632562d44d908877244854250ce2,
        //hotelRoomNo=8082, incomeMoney=60.0, belongDate=2021-03}
        for (Map<String,Object> incomeInfo : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("酒店名称", incomeInfo.get("hotelName").toString());
            map.put("酒店房间号", incomeInfo.get("hotelRoomNo").toString());
            map.put("房间收益", incomeInfo.get("incomeMoney").toString());
            map.put("所属日期", incomeInfo.get("belongDate").toString());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
	}

	@Override
	public void downloadFindInComeByHotelId(List<IncomeInfo> all, HttpServletResponse response) throws IOException {
		// TODO Auto-generated method stub
		DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		DateTimeFormatter dateDtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        List<Map<String, Object>> list = new ArrayList<>();
        //IncomeInfo(id=daabc065a63f4a58900fec6b6cb9dd80, hotelId=0001, hotelName=重庆大酒店, hotelRoomId=aea0632562d44d908877244854250ce2, hotelRoomNo=8082, ip=127.0.0.2, mac=12:23:34:42, price=10.0, limitTime=3600, timeReslut=66529, incomeMoney=10.00, belongDate=2021-03-04, isClose=1, createBy=null, updateBy=null, createTime=null, updateTime=null, isEnable=1)
        for (IncomeInfo incomeInfo : all) {
            Map<String,Object> map = new LinkedHashMap<>();
//          map.put("酒店ID", incomeInfo.getHotelId());
            map.put("酒店名称", incomeInfo.getHotelName());
//          map.put("酒店房间ID", incomeInfo.getHotelRoomId());
            map.put("酒店房间号", incomeInfo.getHotelRoomNo());
            map.put("设备IP", incomeInfo.getIp());
            map.put("设备MAC", incomeInfo.getMac());
            map.put("单价", incomeInfo.getPrice());
            map.put("有效时长", incomeInfo.getLimitTime());
            map.put("总的开机时间", incomeInfo.getTimeReslut());
            map.put("收益额", incomeInfo.getIncomeMoney());
            map.put("收益月份", incomeInfo.getBelongDate() == null ? "" : dateDtf.format(incomeInfo.getBelongDate()));
            map.put("是否结算：1、表示未结算  2、表示结算中  0、表示已结算", incomeInfo.getIsClose());
            map.put("创建者", incomeInfo.getCreateBy());
            map.put("更新者", incomeInfo.getUpdateBy());
            map.put("创建时间", incomeInfo.getCreateTime()  == null ? "" : dtf.format(incomeInfo.getCreateTime()));
            map.put("更新时间", incomeInfo.getUpdateTime() == null ? "" : dtf.format(incomeInfo.getUpdateTime()));
            map.put("数据状态", incomeInfo.getIsEnable());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
	}

}
